package com.leyou.gateway.filters;

import com.leyou.common.auth.entity.Payload;
import com.leyou.common.auth.entity.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.gateway.config.FilterProperties;
import com.leyou.gateway.config.JwtProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    @Autowired
    private JwtProperties prop;

    @Autowired
    private FilterProperties filterProperties;


    /**
     * 权限的控制：鉴权
     * @param exchange      用于获取请求数据
     * @param chain         过滤器链
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            // 获取请求
            ServerHttpRequest request = exchange.getRequest();
            // 过滤白名单
            if(allowPath(request)){
                // 如果是白名单的url放行
                log.info("【网关】访问服务放行 : {}，", request.getURI().getPath());
                return chain.filter(exchange);
            }
            // ============================================================
            // 获取cookie
            HttpCookie cookie = request.getCookies().getFirst(prop.getUser().getCookieName());
            // 如果cookie为空，直接返回401
            if(cookie!=null){
                // 获取cookie的值
                //eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyIjoie1wiaWRcIjoyOSxcInVzZXJuYW1lXCI6XCJ4aWFvZmVpZmVpXCIsXCJyb2xlXCI6XCJndWVzdFwifSIsImp0aSI6Ik9ESmlPRGRqTVRjdFlXTmhOaTAwWXpkaUxXSXpOalV0TkRSallUWmhaV0ppT1dNdyIsImV4cCI6MTU4MTE1NDA0MH0.iLW7vESmt5P_eaJoeCxOJS55Y0eu16nYnYZ83qHwESTpWUMyPHI5vGm6BB-3vw4eijJodwmttWlQnHeH05w9MjzzW9QLw5WS7umKEmz8lNsPsATRpuoORS1nJ04B1VlUpsGyjXH7aqXqQy2w5I3M2cY9XzC3zGiFYQDLHvqg5JBvbF_fP-3rMKgq3TYMo69MI05Y_YltQlu-x_is6w5YYOedEBJtMR5TIfPH4oT6ZtfvciHTExpIg_JQcx9DlQ5y3_0GVeWJV_GTdrIb2CGQFmbN07zwiGyfgynbkFGkawTVPLgOcutKwR41PzIIm1SpdIgqQDycROr0Kq4NStvVhw
                String token = cookie.getValue();
                // 校验token
                Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, prop.getPublicKey(), UserInfo.class);
                // 如果执行到这里，说明token可以使用的
                //==============================================
                UserInfo userInfo = payload.getUserInfo();
                String role = userInfo.getRole();
                /*if(有权限){
                    放行
                }else{
                    没权限抛异常
                }*/
                // 用户的角色
                System.out.println("角色======>"+role);
                // 获取请求的url
                String path = request.getURI().getPath();
                System.out.println("路径======> "+path);
                String method = request.getMethodValue();
                System.out.println("方法类型：=====>"+method);
                // 在这里就可以判断用户是否有这个权限，如果没有，可以抛出异常
                // TODO 判断权限，此处暂时空置，等待权限服务完成后补充
                log.info("【网关】用户{},角色{}。访问服务{} : {}，", userInfo.getUsername(), role, method, path);
                //==============================================
            }

        } catch (Exception e) {
            // 没有权限，阻断往下访问
            log.error("【网关】鉴权失败信息：{}",e.getMessage());
            // token无效，返回401
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // 放行
        return chain.filter(exchange);
    }

    /**
     * 白名单过滤
     * @param request
     * @return
     */
    private boolean allowPath(ServerHttpRequest request) {
        // 获取请求路径
        String path = request.getURI().getPath();
        // 白名单
        List<String> allowPaths = filterProperties.getAllowPaths();
        for (String allowPath : allowPaths) {
            if(path.startsWith(allowPath)){
                // 在白名单中返回true
                return true;
            }
        }
        // 执行到这里说明没有在白名单中
        return false;
    }

    /**
     * 如果有多个过滤器，这个数字越小，越先执行
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
